/**
 * Copyright &copy; 2015-2015  Jeedcp All rights reserved.
 */
package com.jeedcp.modules.sys.service;

import com.github.pagehelper.PageHelper;

import com.jeedcp.common.cache.EhCacheServiceBean;
import com.jeedcp.common.persistence.Pagination;
import com.jeedcp.common.security.Digests;
import com.jeedcp.common.service.BaseService;
import com.jeedcp.common.service.ServiceException;
import com.jeedcp.common.utils.Encodes;
import com.jeedcp.common.utils.StringUtils;
import com.jeedcp.modules.sys.dao.MenuDao;
import com.jeedcp.modules.sys.dao.RoleDao;
import com.jeedcp.modules.sys.dao.UserDao;
import com.jeedcp.modules.sys.entity.Menu;
import com.jeedcp.modules.sys.entity.Office;
import com.jeedcp.modules.sys.entity.Role;
import com.jeedcp.modules.sys.entity.User;

import com.jeedcp.modules.sys.utils.CurrentUserUtils;
import com.jeedcp.modules.sys.utils.DataFilterUtils;

import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 系统管理，安全相关实体的管理类,包括用户、角色、菜单.
 * @author jeedcp
 * @version 2013-12-05
 */
@Service
@Transactional(readOnly = true)
public class SystemService extends BaseService {
	
	public static final String HASH_ALGORITHM = "SHA-1";
	public static final int HASH_INTERATIONS = 1024;
	public static final int SALT_SIZE = 8;
	
	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private MenuDao menuDao;
	@Autowired
	private SessionDAO sessionDao;
	@Autowired
	EhCacheServiceBean ehCacheServiceBean;

	public SessionDAO getSessionDao() {
		return sessionDao;
	}

	//-- User Service --//
	
	/**
	 * 获取用户
	 * @param id
	 * @return
	 */
	public User getUser(String id) {
        User user = null;
        if (id !=  null) {
            user = userDao.get(id);
            if (user != null) {
                user.setRoleList(roleDao.findList(new Role(user)));
            }
        }
		return user;
	}

	/**
	 * 根据登录名获取用户
	 * @param loginName
	 * @return
	 */
	public User getUserByLoginName(String loginName) {
        User user = null;
        if (loginName != null){
            user = userDao.getByLoginName(new User(null, loginName));
            if (user != null){
                user.setRoleList(roleDao.findList(new Role(user)));
            }
        }
        return user;
	}
	
	public Pagination<User> findUser(Pagination<User> page, User user) {
		// 生成数据权限过滤条件（dsf为dataScopeFilter的简写，在xml中使用 ${sqlMap.dsf}调用权限SQL）
		user.getSqlMap().put("dsf", DataFilterUtils.dataScopeFilter(CurrentUserUtils.getUser(), "o", "a"));
		// 执行分页查询
        PageHelper.startPage(page.getPageNum(), page.getPageSize());

        logger.debug("findlist page user start"+ System.currentTimeMillis());
        List<User> list = userDao.findList(user);
        logger.debug("findlist page user end"+ System.currentTimeMillis());
        //用PageInfo对结果进行包装
        Pagination pageInfo = new Pagination(list);
//        todo delete
        logger.debug("findlist user 1 start"+ System.currentTimeMillis());
        userDao.findList(user);
        logger.debug("findlist user 1 end and 2 start"+ System.currentTimeMillis());
        userDao.findList(user);
        logger.debug("findlist user 2 end"+ System.currentTimeMillis());
		return pageInfo;
	}


	/**
	 * 无分页查询人员列表
	 * @param user
	 * @return
	 */
	public List<User> findUser(User user){
		// 生成数据权限过滤条件（dsf为dataScopeFilter的简写，在xml中使用 ${sqlMap.dsf}调用权限SQL）
		user.getSqlMap().put("dsf", DataFilterUtils.dataScopeFilter(CurrentUserUtils.getUser(), "o", "a"));
		List<User> list = userDao.findList(user);
		return list;
	}

	/**
	 * 通过部门ID获取用户列表，仅返回用户id和name（树查询用户时用）
	 * @param officeId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<User> findUserByOfficeId(String officeId) {
		List<User> list = null;
		if (officeId != null){
			User user = new User();
			user.setOffice(new Office(officeId));
			list = userDao.findUserByOfficeId(user);
		}
		return list;
	}
	
	@Transactional(readOnly = false)
	public void saveUser(User user) {
		if (StringUtils.isBlank(user.getId())){
            CurrentUserUtils.preInsert(user);
			userDao.insert(user);
		}else{
			// 清除原用户机构用户缓存
			User oldUser = userDao.get(user.getId());
//			if (oldUser.getOffice() != null && oldUser.getOffice().getId() != null){
//				ehCacheServiceBean.remove(UserUtils.USER_CACHE, UserUtils.USER_CACHE_LIST_BY_OFFICE_ID_ + oldUser.getOffice().getId());
//			}
			// 更新用户数据
            CurrentUserUtils.preUpdate(user);
			userDao.update(user);
		}
		if (StringUtils.isNotBlank(user.getId())){
			// 更新用户与角色关联
			userDao.deleteUserRole(user);
			if (user.getRoleList() != null && user.getRoleList().size() > 0){
				userDao.insertUserRole(user);
			}
//            else{
//				throw new ServiceException(user.getLoginName() + "没有设置角色！");
//			}
			// 清除用户缓存
//			UserUtils.clearCache(user);
//			// 清除权限缓存
//			systemRealm.clearAllCachedAuthorizationInfo();
		}
//        todo test
//        throw new ServiceException("1111111");
	}

    @Transactional(readOnly = false)
    public void insertUser(User user) {
        if (StringUtils.isNotBlank(user.getId())){
            userDao.insert(user);
        }else{
            throw new ServiceException(user + "id is null");
        }
        if (StringUtils.isNotBlank(user.getId())){
            // 更新用户与角色关联
            userDao.deleteUserRole(user);
            if (user.getRoleList() != null && user.getRoleList().size() > 0){
                userDao.insertUserRole(user);
            }
        }
    }



    @Transactional(readOnly = false)
	public void updateUserInfo(User user) {
        CurrentUserUtils.preUpdate(user);
		userDao.updateUserInfo(user);
		// 清除用户缓存
//		UserUtils.clearCache(user);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
	}
	
	@Transactional(readOnly = false)
	public void deleteUser(User user) {
		userDao.delete(user);
		// 清除用户缓存
//		UserUtils.clearCache(user);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
	}
	
	@Transactional(readOnly = false)
	public void updatePasswordById(String id, String loginName, String newPassword) {
		User user = new User(id);
		user.setPassword(entryptPassword(newPassword));
		userDao.updatePasswordById(user);
		// 清除用户缓存
		user.setLoginName(loginName);
//		UserUtils.clearCache(user);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
	}
	
	@Transactional(readOnly = false)
	public void updateUserLoginInfo(User user) {
		// 保存上次登录信息
		user.setOldLoginIp(user.getLoginIp());
		user.setOldLoginDate(user.getLoginDate());
		// 更新本次登录信息
		user.setLoginIp(CurrentUserUtils.getSession().getHost());
		user.setLoginDate(new Date());
		userDao.updateLoginInfo(user);
	}
	
	/**
	 * 生成安全的密码，生成随机的16位salt并经过1024次 sha-1 hash
	 */
	public static String entryptPassword(String plainPassword) {
		byte[] salt = Digests.generateSalt(SALT_SIZE);
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return Encodes.encodeHex(salt)+ Encodes.encodeHex(hashPassword);
	}
	
	/**
	 * 验证密码
	 * @param plainPassword 明文密码
	 * @param password 密文密码
	 * @return 验证成功返回true
	 */
	public static boolean validatePassword(String plainPassword, String password) {
		byte[] salt = Encodes.decodeHex(password.substring(0,16));
		byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
		return password.equals(Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword));
	}
	
	/**
	 * 获得活动会话
	 * @return
	 */
//	public Collection<Session> getActiveSessions(){
//		return sessionDao.getActiveSessions(false);
//	}
	
	//-- Role Service --//
	
	public Role getRole(String id) {
		return roleDao.get(id);
	}

	public Role getRoleByName(String name) {
		Role r = new Role();
		r.setName(name);
		return roleDao.getByName(r);
	}
	
	public Role getRoleByEnname(String enname) {
		Role r = new Role();
		r.setEnname(enname);
		return roleDao.getByEnname(r);
	}
	
	public List<Role> findRole(Role role){
		return roleDao.findList(role);
	}
	
	public List<Role> findAllRole(){
        List<Role> roleList = null;
        if (roleList == null){
            User user = CurrentUserUtils.getUser();
            if (user.isAdmin()){
                roleList = roleDao.findAllList(new Role());
            }else{
                Role role = new Role();
                role.getSqlMap().put("dsf", DataFilterUtils.dataScopeFilter(user, "o", "u"));
                roleList = roleDao.findList(role);
            }
        }
        return roleList;
	}
	
	@Transactional(readOnly = false)
	public void saveRole(Role role) {
		if (StringUtils.isBlank(role.getId())){
            CurrentUserUtils.preInsert(role);
			roleDao.insert(role);
		}else{
            CurrentUserUtils.preUpdate(role);
			roleDao.update(role);
		}
		// 更新角色与菜单关联
		roleDao.deleteRoleMenu(role);
		if (role.getMenuList().size() > 0){
			roleDao.insertRoleMenu(role);
		}
		// 更新角色与部门关联
		roleDao.deleteRoleOffice(role);
		if (role.getOfficeList().size() > 0){
			roleDao.insertRoleOffice(role);
		}
		// 清除用户角色缓存
//		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void deleteRole(Role role) {
		roleDao.delete(role);
		// 清除用户角色缓存
//		UserUtils.removeCache(UserUtils.CACHE_ROLE_LIST);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
	}
	
	@Transactional(readOnly = false)
	public Boolean outUserInRole(Role role, User user) {
		List<Role> roles = user.getRoleList();
		for (Role e : roles){
			if (e.getId().equals(role.getId())){
				roles.remove(e);
				saveUser(user);
				return true;
			}
		}
		return false;
	}
	
	@Transactional(readOnly = false)
	public User assignUserToRole(Role role, User user) {
		if (user == null){
			return null;
		}
		List<String> roleIds = user.getRoleIdList();
		if (roleIds.contains(role.getId())) {
			return null;
		}
		user.getRoleList().add(role);
		saveUser(user);
		return user;
	}

	//-- Menu Service --//
	
	public Menu getMenu(String id) {
		return menuDao.get(id);
	}


    /**
     * 获取当前用户授权菜单
     * @return
     */
    public List<Menu> getMenuListById(String id){
        List<Menu> menuList = null;
        if (menuList == null){
            User user = userDao.get(id);
            if (user.isAdmin()){
                menuList = menuDao.findAllList(new Menu());
            }else{
                Menu m = new Menu();
                m.setUserId(user.getId());
                menuList = menuDao.findByUserId(m);
            }
        }
        return menuList;
    }


    public List<Menu> findAllMenu(){
        @SuppressWarnings("unchecked")
        List<Menu> menuList = null;
        if (menuList == null){
            User user = CurrentUserUtils.getUser();
            if (user.isAdmin()){
                menuList = menuDao.findAllList(new Menu());
            }else{
                Menu m = new Menu();
                m.setUserId(user.getId());
                menuList = menuDao.findByUserId(m);
            }
        }
        return menuList;
	}
	
	@Transactional(readOnly = false)
	public void saveMenu(Menu menu) {
		
		// 获取父节点实体
		menu.setParent(this.getMenu(menu.getParent().getId()));
		
		// 获取修改前的parentIds，用于更新子节点的parentIds
		String oldParentIds = menu.getParentIds(); 
		
		// 设置新的父节点串
		menu.setParentIds(menu.getParent().getParentIds()+menu.getParent().getId()+",");

		// 保存或更新实体
		if (StringUtils.isBlank(menu.getId())){
            CurrentUserUtils.preInsert(menu);
			menuDao.insert(menu);
		}else{
            CurrentUserUtils.preUpdate(menu);
			menuDao.update(menu);
		}
		
		// 更新子节点 parentIds
		Menu m = new Menu();
		m.setParentIds("%,"+menu.getId()+",%");
		List<Menu> list = menuDao.findByParentIdsLike(m);
		for (Menu e : list){
			e.setParentIds(e.getParentIds().replace(oldParentIds, menu.getParentIds()));
			menuDao.updateParentIds(e);
		}
		// 清除用户菜单缓存
//		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
//		ehCacheServiceBean.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}

	@Transactional(readOnly = false)
	public void updateMenuSort(Menu menu) {
		menuDao.updateSort(menu);
		// 清除用户菜单缓存
//		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
//		ehCacheServiceBean.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}

	@Transactional(readOnly = false)
	public void deleteMenu(Menu menu) {
		menuDao.delete(menu);
		// 清除用户菜单缓存
//		UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
//		// 清除权限缓存
//		systemRealm.clearAllCachedAuthorizationInfo();
		// 清除日志相关缓存
//		ehCacheServiceBean.remove(LogUtils.CACHE_MENU_NAME_PATH_MAP);
	}
	

}
